#include "viewobject.h"

void ViewObject::SetObjectParam(ParamObject &param)//设置基本属性
{
    if (NULL == m_objectParam)
        return;

    m_objectParam->SetIndex(param.GetIndex());
    m_objectParam->SetStId(param.GetStId());
    m_objectParam->SetObjectName(param.GetObjectName());
    m_objectParam->SetName(param.GetName());
    m_objectParam->SetPos(param.GetPos());
    m_objectParam->SetWidth(param.GetWidth());
    m_objectParam->SetHeight(param.GetHeight());
    m_objectParam->SetScale(param.GetScale());
    m_objectParam->SetRandom(param.GetRandom());
    m_objectParam->SetShowLeft(param.GetShowLeft());
}

QString ViewObject::GetFinalUrl()
{
    if (m_hq_label != NULL)
        return m_hq_label->GetUrl();
    return "";
}

void ViewObject::Update(std::string json)
{
    SetAttribute(json);
    ShowObject();
    //更新之后有可能为了截屏被取消选中了，所以更新后选中一下,而且不是改变选中的样式
    //和触发点击事件事件一样需要通知structureview是否有控件name名称改变
    emit sgl_viewobject_select_to_editwidget(m_objectParam->GetRandom());
    StartHqv();//保证Hqv最后显示
}

void ViewObject::set_style()//设置控件选择样式
{
    QString qss = styleSheet();
    if (mSelect)
    {
        if (qss == "")
        {
            qss.append("border-left: 2px dotted blue;"
                       "border-right: 2px dotted blue;"
                       "border-top: 2px dotted blue;"
                       "border-bottom: 2px dotted blue;");
        }

        int index, end_index;
        if (qss.contains("border-left:"))
        {
            index = qss.indexOf("border-left:");
            end_index = qss.indexOf(";", index);
            qss.replace(index, end_index - index, "border-left: 2px dotted blue");
        }

        if (qss.contains("border-right:"))
        {
            index = qss.indexOf("border-right:");
            end_index = qss.indexOf(";", index);
            qss.replace(index, end_index - index, "border-right: 2px dotted blue");
        }

        if (qss.contains("border-top:"))
        {
            index = qss.indexOf("border-top:");
            end_index = qss.indexOf(";", index);
            qss.replace(index, end_index - index, "border-top: 2px dotted blue");
        }

        if (qss.contains("border-bottom:"))
        {
            index = qss.indexOf("border-bottom:");
            end_index = qss.indexOf(";", index);
            qss.replace(index, end_index - index, "border-bottom: 2px dotted blue");
        }
    }
    else
    {
        if (qss == "")
        {
            qss.append("border-left: 0px;"
                       "border-right: 0px;"
                       "border-top: 0px;"
                       "border-bottom: 0px;");
        }

        int index, end_index;
        if (qss.contains("border-left:"))
        {
            index = qss.indexOf("border-left:");
            end_index = qss.indexOf(";", index);
            qss.replace(index, end_index - index, "border-left: 0px");
        }

        if (qss.contains("border-right:"))
        {
            index = qss.indexOf("border-right:");
            end_index = qss.indexOf(";", index);
            qss.replace(index, end_index - index, "border-right: 0px");
        }

        if (qss.contains("border-top:"))
        {
            index = qss.indexOf("border-top:");
            end_index = qss.indexOf(";", index);
            qss.replace(index, end_index - index, "border-top: 0px");
        }

        if (qss.contains("border-bottom:"))
        {
            index = qss.indexOf("border-bottom:");
            end_index = qss.indexOf(";", index);
            qss.replace(index, end_index - index, "border-bottom: 0px");
        }
    }

    setStyleSheet(qss);
}

void ViewObject::Select()
{
    mSelect = true;
    set_style();
}

void ViewObject::Cancel()
{
    mSelect = false;
    set_style();
}

void ViewObject::Up()
{
    if (!mSelect)
        return;
    QPoint pos = m_objectParam->GetPos();
    QPoint point(QPoint(0, 1));
    pos -= point;
    m_objectParam->SetPos(pos);
    move(pos);
    emit sgl_viewobject_update_to_editwidget(m_objectParam->GetRandom());
}

void ViewObject::Down()
{
    if (!mSelect)
        return;
    QPoint pos = m_objectParam->GetPos();
    QPoint point(QPoint(0, 1));
    pos += point;
    m_objectParam->SetPos(pos);
    move(pos);
    emit sgl_viewobject_update_to_editwidget(m_objectParam->GetRandom());
}

void ViewObject::Right()
{
    if (!mSelect)
        return;
    QPoint pos = m_objectParam->GetPos();
    QPoint point(QPoint(1, 0));
    pos += point;
    m_objectParam->SetPos(pos);
    move(pos);
    emit sgl_viewobject_update_to_editwidget(m_objectParam->GetRandom());
}

void ViewObject::Left()
{
    if (!mSelect)
        return;
    QPoint pos = m_objectParam->GetPos();
    QPoint point(QPoint(1, 0));
    pos -= point;
    m_objectParam->SetPos(pos);
    move(pos);
    emit sgl_viewobject_update_to_editwidget(m_objectParam->GetRandom());
}

void ViewObject::location(int x, int y, int w, int h)
{
    x = x + mOffsetX;
    int new_x = x - (w >>1);
    int new_y = y - (h >>1);
    setGeometry(new_x, new_y, w, h);
}

void ViewObject::AddSuffix(QString &path)
{
    if (mProtocolData == NULL || mProtocolData->suffix == "" || path == "")
        return;

    QString suffix = mProtocolData->suffix;

    QString old_path = path;

    if (path.contains("."))
    {
        QStringList name_list = path.split(".");
        path = QString("%1_%2.%3").arg(name_list.at(0))
                .arg(suffix)
                .arg(name_list.at(1));

        if (name_list.at(1) == "hqv")
        {
            QFileInfo info(mPrefix + path);
            if (!info.isDir())
                path = old_path;
        }
        else
        {
            QFileInfo info(mPrefix + path);
            if (!info.isFile())
                path = old_path;
        }
    }
}

void ViewObject::StartHqv()
{
    if (m_hq_label != NULL)
        m_hq_label->StartHqv();
}

QString ViewObject::FindHqt(QString prefix, QString url)
{
    /*
         * 不使用纯虚，因为有些控件不支持这个函数
        */
    Q_UNUSED(prefix);
    Q_UNUSED(url);
    return "";
}

QString ViewObject::FindCss(QString prefix, QString url_origin, QString url_with_suffix)
{
    /*
         * 不使用纯虚，因为有些控件不支持这个函数
         * 默认直接返回原来的url不找css，某些控件不需要寻找
        */
    Q_UNUSED(prefix);
    Q_UNUSED(url_origin);
    return url_with_suffix;
}

QString ViewObject::FindFile(QString prefix, QString name)
{
    if (name == "" || name == "hide")
        return "";

    QString ret;

    ret = myapp::find_file_single(prefix, name);
    if (ret != "")
    {
        AddSuffix(ret);
        return ret;
    }

    QStringList list = name.split("_");

    //欲到站全线图，到站全线图，区别的找区别的图，和全线图相同的还是找all开头的图
    if (list.first().contains("all") && list.first() != "all")
    {
        name = name.replace(list.first(), QString("all"));
        QString ret = myapp::find_file_single(prefix, name);
        if (ret != "")
        {
            AddSuffix(ret);
            return ret;
        }
    }

    //如果是线，先去id再找默认pass
    if ((name.contains("line")) && myapp::isDigitStr(list.last()))
    {
        name = name.left(name.size() - list.last().size() - 1);
        ret = myapp::find_file_single(prefix, name);
        if (ret != "")
        {
            AddSuffix(ret);
            return ret;
        }
    }

    //越战和交路若找不到图就找pass，但是pass还是找不到不能返回空，还要去找改成pass之后是不是有去掉id的图
    if (name.contains("cross"))
    {
        name = name.replace(QString("cross"), QString("pass"));
        QString ret = myapp::find_file_single(prefix, name);
        if (ret != "")
        {
            AddSuffix(ret);
            return ret;
        }
    }
    if (name.contains("skip"))
    {
        name = name.replace(QString("skip"), QString("pass"));
        QString ret = myapp::find_file_single(prefix, name);
        if (ret != "")
        {
            AddSuffix(ret);
            return ret;
        }
    }

    //站点若没站点数字区分，那么去掉数字去找相同的点，点先找默认pass再去id
    if ((name.contains("point")) && myapp::isDigitStr(list.last()))
    {
        name = name.left(name.size() - list.last().size() - 1);
        ret = myapp::find_file_single(prefix, name);
        if (ret != "")
        {
            AddSuffix(ret);
            return ret;
        }
    }

    if (name.contains("next_station") || name.contains("now_station") || name.contains("start_station") || name.contains("terminal_station"))
    {
        QString single_name = list.at(1) + QString("_") + list.at(2) + QString("_") + list.at(3);
        ret = myapp::find_file_single(prefix, single_name);
        if (ret != "")
        {
            AddSuffix(ret);
            return ret;
        }
    }
    //前面都找不到最终去寻找配置文件
    return FindHqt(prefix, name);
}

void ViewObject::FinalShow(QString url)
{
    //跨xml控件,工具中正常显示
    if (mProtocolData != NULL)
    {
        /*跨xml控件，模拟或者板卡运行注意点：
            1、显示过则不再重新显示，除非做了修改
            2、不管是否显示过都必须raise()提升显示，除非第一次显示
            3、itemschange必须要修改acrossxml控件所在xml的图才行!!!，别的图执行itemschange会导致找不到qss1因为找样式的时候会加图的前缀(all interval arrive)。
            4、若有两幅图有两个滚动条name不能重名
            5、滚动控件必须要提升zindex否则换xml时即使raise()也显示不出来
            */
        if (m_objectParam->GetName().contains("acrossxml"))
        {
            if (m_acrossxml_obj_has_shown)
            {
                raise();//提升显示避免被覆盖

                //若没修改才返回，有修改则重新加载
                if (!m_change)
                    return;
            } else
            {
                m_acrossxml_obj_has_shown = true;
            }
        }
    }
    else
    {
        delete m_hq_label;
        m_hq_label = NULL;
    }


    if (m_hq_label == NULL)
    {
        m_hq_label = new HqLabel();
        m_layout->addWidget(m_hq_label, 0, Qt::AlignCenter);
    }

    //通过基类控件的大小设置超级label的大小
    m_hq_label->setFixedSize(size());

    //截屏之前改成未选择状态，否则有虚线框
    Cancel();

    m_hq_label->SetContent(mPrefix, url);

    //工具中显示的时候需要这个show()，因为母窗口以及show了，需要子控件单独去show
    //模拟或者板卡运行不需要show，直接show dynamicmapmanagewindow母窗口就好了
    show();

    //需要show之后才能截屏
    if (m_hq_label->GetGrabFlag() == TwoFrameScale || m_hq_label->GetGrabFlag() == Scale)
        m_hq_label->ReRunHqtRotateGrabAnimation((Animation)m_hq_label->GetGrabFlag());
}

void ViewObject::RunItemsChange(QMap<QString, change_property> items_change)
{
    if (items_change.size() == 0)
        return;

    for (auto it = items_change.begin(); it != items_change.end(); it++)
    {
        if (!it.key().compare(m_objectParam->GetName()))
        {
            LOG_QDEBUG << m_objectParam->GetName();
            m_change = true;

            if (it.value().x != DEFAULTVAL)
                m_change_x = it.value().x;
            else
                m_change_x = m_objectParam->GetX();
            if (it.value().y != DEFAULTVAL)
                m_change_y = it.value().y;
            else
                m_change_y = m_objectParam->GetY();
            if (it.value().w != DEFAULTVAL)
                m_change_w = it.value().w;
            else
                m_change_w = m_objectParam->GetWidth();
            if (it.value().h != DEFAULTVAL)
                m_change_h = it.value().h;
            else
                m_change_h = m_objectParam->GetHeight();
            if (it.value().content != "")
            {
                url = it.value().content;
            }
        } else
        {
            //itemschange改完之后需要把m_change变量改回false否则影响下面判断，门隔离全屏之后取消判断m_change==true的话会仍然使用全屏大小的图
            m_change = false;
        }
    }
}

void ViewObject::ShowUrl()
{

#ifdef __WIN32__
    if (mPrefix == "")
        mPrefix = QString("%1/img/").arg(myapp::mDynamicMapParam->m_project_path);
#endif
    if (mProtocolData != NULL)
        RunItemsChange(mProtocolData->items_change);

    //根据items_change或者设置的属性确定基类控件的大小
    if (m_change)
    {
        LOG_QDEBUG << "change";
        LOG_QDEBUG << m_change_x << m_change_y << m_change_w << m_change_h;
        location(m_change_x, m_change_y, m_change_w, m_change_h);
    }
    else
    {
        LOG_QDEBUG << "no change";
        LOG_QDEBUG << m_objectParam->GetX() << m_objectParam->GetY() << m_objectParam->GetWidth() << m_objectParam->GetHeight();
        location(m_objectParam->GetX(), m_objectParam->GetY(), m_objectParam->GetWidth(), m_objectParam->GetHeight());
    }
    //如果是滚动条可能会相同但是还是需要正常往下走的
    if (url != old_url || m_objectParam->GetName().contains("acrossxml") || mProtocolData == NULL)
    {
        LOG_QDEBUG << "old url:" << old_url;
        LOG_QDEBUG << "url:" << url;
        old_url = url;
    }
    else
    {
        //一样的直接显示出来即可
        LOG_QDEBUG << url << " is not change, continue!";
        show();
        return;
    }

    LOG_QDEBUG << m_objectParam->GetObjectName() << "before find: " << url;

    /*
            虚函数：子类需要实现，若不实现则直接返回空

            若url为空或者是hide，则返回空;

            StationView  优先找图(找到则返回url.png url.hqv url.gif)，找不到图再找配置文本(value.hqt)，找不到文本返回空

            NextView或者其他文本类控件同StationView

            SingleView   优先找图(找到则返回url.png url.hqv url.gif)，找不到图看是否包含##(css##url)，包含则会搜索##后面的图，
                         找到图则返回css##url.png...，都找不到则直接返回url.hqt 或者 css##url.hqt
        */
    url_with_suffix = FindFile(mPrefix, url);
    LOG_QDEBUG << m_objectParam->GetObjectName() << "after find pic: " << url_with_suffix;

    /*
            若不在子类实现，则直接不做操作，返回原来的url

            StationView 拿到的url是  text.hqt pic.png等等，会根据text或者url去配置文件寻找相应的css样式，寻找区别点在子类实现，找到之后则加在url前面以"##"分隔
        */
    QString url_with_style = FindCss(mPrefix, url, url_with_suffix);

    LOG_QDEBUG << m_objectParam->GetObjectName() << "after find style: " << url_with_style;

    FinalShow(url_with_style);
}

void ViewObject::ReLoadRes()
{
    //理论上前一次数据具备，此次数据只是某些控件作了小的差异修改
    LOG_QDEBUG << m_objectParam->GetObjectName() << "before refind res: " << url;
    QString url_refind = FindFile(mPrefix, url);//重新找资源
    LOG_QDEBUG << m_objectParam->GetObjectName() << "after refind res: " << url_refind;

    LOG_QDEBUG << m_objectParam->GetObjectName() << "old url_with_suffix:" << url_with_suffix;
    if (url_refind != url_with_suffix)//真正找到了差异的资源才进行重新加载的动作
    {
        m_hq_label->ReLoadUrl(mPrefix, url_refind);//只是重新加载资源不该显示和位置
        url_with_suffix = url_refind;
    }
    //重新显示不会寻找css样式，若有样式修改都会全部删除重新显示，只是修改文本或者图片
}

void ViewObject::AddSuffixAndReloadPic(QString suffix)
{
    //更新后缀
    mProtocolData->suffix = suffix;
    ReLoadRes();
}

void ViewObject::ReRunItemsChangeAndShow(QMap<QString, change_property> items_change)
{
    RunItemsChange(items_change);

    ReLoadRes();

    if (m_change)
        location(m_change_x, m_change_y, m_change_w, m_change_h);
    else
        location(m_objectParam->GetX(), m_objectParam->GetY(), m_objectParam->GetWidth(), m_objectParam->GetHeight());
}

void ViewObject::slt_rightButton_copy()
{
    if (!mSelect)
        return;
    emit signalCopy(m_objectParam->GetRandom());
}

void ViewObject::slt_rightButton_edit()
{
    if (!mSelect)
        return;
    emit signalEdit(m_objectParam->GetRandom());
}

void ViewObject::slt_rightButton_delete()
{
    if (!mSelect)
        return;
    emit signalDelete(m_objectParam->GetRandom());
}

void ViewObject::slt_BeginShow()
{
    ShowObject();
}

#ifndef __linux__
void ViewObject::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton)
    {
        //移动的时候包括最终显示控件的时候都是按照左顶点去显示控件
        move(event->globalPos() - mOffset);

        //但是在右下角显示坐标值的时候统一显示中点坐标，否则选中控件是选中中点坐标，移动一下又变成了左顶点坐标，param中存储的一律是中点坐标
        m_objectParam->SetPos(event->globalPos() - mOffset + QPoint(m_objectParam->GetWidth()/2, m_objectParam->GetHeight()/2));
        emit sgl_viewobject_update_to_editwidget(m_objectParam->GetRandom());
    }
}
void ViewObject::mousePressEvent(QMouseEvent *event)
{
    if (event->modifiers() == Qt::ControlModifier && event->button() == Qt::LeftButton)
    {
        emit signalSelect(m_objectParam->GetRandom());
    }
    else if (event->button() == Qt::LeftButton)
    {
        mOffset = event->globalPos() - pos();
        emit sgl_viewobject_select_to_editwidget(m_objectParam->GetRandom());
    }
    else
        QWidget::mousePressEvent(event);
}
void ViewObject::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Delete)
    {
        if (mSelect)
        {
            emit signalDelete(m_objectParam->GetRandom());
        }
    }
    else if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_C))
    {
        if (mSelect)
        {
            emit signalCopy(m_objectParam->GetRandom());
        }
    }
    else if (event->key() == Qt::Key_Left)
    {
        Left();
    }
    else if (event->key() == Qt::Key_Up)
    {
        Up();
    }
    else if (event->key() == Qt::Key_Right)
    {
        Right();
    }
    else if (event->key() == Qt::Key_Down)
    {
        Down();
    }
    else
        QWidget::keyPressEvent(event);
}
#endif
